<?php
namespace Modules\Cli\Tasks;

use Common\Models\UserModel;
use Common\Models\UserTeamModel;
use Common\Models\UserWalletGoodsLogModel;

class MainTask extends TaskBase {
  private $currentTime;

  private $logger;

  public function initialize() {
    $this -> currentTime = time();

    $this -> logger = new \Phalcon\Logger\Adapter\File(BASE_PATH . 'runtime/logger/cli_'.date('Ymd').'.log');
    //$this -> logger -> setFormatter(new \Phalcon\Logger\Formatter\Json()); 
  }

  public function mainAction() {
    set_time_limit(0);
    ini_set('date.timezone', 'Asia/Shanghai');
    echo 'Executing...';

    $this -> logger -> begin();
    $this -> logger -> notice('————————————————' . $this -> currentTime . '————————————————'); 
    // 获取奖金
    $this -> getReward();
    $this -> logger -> notice('————————————————' . $this -> currentTime . '————————————————');
    $this -> logger -> commit();
  }

  public function getReward() {
    $findUsersReward = UserModel::find([
      'conditions' => 'is_reward = 0',
      'order' => 'user_id ASC'
    ]);
    if(!$findUsersReward -> valid()) {
      $this -> logger -> info('LINE: ' . __LINE__ . ', 无可奖励用户');
      return false;
    }

    $findUsers = UserModel::find([
      'columns' => 'user_id, node_user_id, node_side, user_level, point_award, is_reward',
      'order' => 'user_id DESC'
    ]);

    $users = [];
    foreach($findUsers as $user) {
      $users[$user -> user_id] = $user;
    }
    $childrenUsers = [];
    foreach($users as $user) {
      switch($user -> node_side) {
        case 1:
        case 2:
          $childrenUsers[$user -> node_user_id][$user -> node_side] = $user;
          break;
        default:
          $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $user -> user_id . '此用户节点存在问题, node_side = ' . $user -> node_side);
          break;
      }
    }

    // 发放奖励手续费
    $USER_GOODS_REWARD_SERVICE_CHARGE = $this -> getParameter('USER_GOODS_REWARD_SERVICE_CHARGE');
    $USER_GOODS_REWARD_SERVICE_CHARGE['value'] = $USER_GOODS_REWARD_SERVICE_CHARGE['value'] / 100;
    // 见点奖获取数量
    $USER_REGISTER_GET_POINT_REWARD_AMOUNT = $this -> getParameter('USER_REGISTER_GET_POINT_REWARD_AMOUNT');
    // 见点奖获取层数
    $USER_REGISTER_GET_POINT_REWARD_LAYER = $this -> getParameter('USER_REGISTER_GET_POINT_REWARD_LAYER');
    // 用户业绩
    $USER_EVERY_ONE_ACHIEVEMENT = $this -> getParameter('USER_EVERY_ONE_ACHIEVEMENT');
    // 用户层碰奖金额
    $USER_WALLET_GOODS_TOUCH_REWARD = $this -> getParameter('USER_WALLET_GOODS_TOUCH_REWARD');

    foreach($findUsersReward as $user) {
      $currentNodeUser = $user;

      // 见点可发代数
      $pointRewardLayer = $USER_REGISTER_GET_POINT_REWARD_LAYER['value'];
      // 层碰奖层数
      $numberOfPlies = 1;
      while(true) {
        echo '...';
        if($currentNodeUser -> node_user_id <= 0) {
          break;
        }

        if($currentNodeUser -> user_id == $currentNodeUser -> node_user_id) {
          $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $currentNodeUser -> user_id . ' == node_user_id: ' . $currentNodeUser -> node_user_id);
          break;
        }

        if(!isset($users[$currentNodeUser -> node_user_id])) {
          $this -> logger -> warning('LINE: ' . __LINE__ . ', node_user_id: ' .  $currentNodeUser -> node_user_id . '此用户节点用户不存在');
          break;
        }
        $parentNodeUser = $users[$currentNodeUser -> node_user_id];

        //层碰奖 start
        if(isset($childrenUsers[$parentNodeUser -> user_id]) && !empty($childrenUsers[$parentNodeUser -> user_id])) {
          $thisLayerUsers = [];
          $separateChildrenLayersUsers = [];
          foreach($childrenUsers[$parentNodeUser -> user_id] as $v) {
            $thisLayerUsers[$numberOfPlies][$v -> user_id] = $v;
            $separateChildrenLayersUsers[$v -> user_id] = [];
          }

          $countThisLayerUesrs = count($thisLayerUsers[$numberOfPlies]);
          if($countThisLayerUesrs > 2) {
            $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $parentNodeUser -> user_id . '此用户下的节点大于2');
          } else if($countThisLayerUesrs > 0 && $countThisLayerUesrs <= 2) {
            for($i=$numberOfPlies;$i>0;$i--) {
              if(!isset($thisLayerUsers[$i])) {
                break;
              }

              foreach($thisLayerUsers[$i] as $v) {
                if(isset($childrenUsers[$v -> user_id]) && !empty($childrenUsers[$v -> user_id])) {
                  foreach($childrenUsers[$v -> user_id] as $cv) {
                    $separateParentsUsers = $cv;
                    $j=1;
                    for(;$j<$numberOfPlies;$j++) {
                      if(array_key_exists($separateParentsUsers -> node_user_id, $separateChildrenLayersUsers)) {
                        break;
                      }
                      if(!isset($users[$separateParentsUsers -> node_user_id])) {
                        $separateParentsUsers = null;
                        break;
                      }
                      $separateParentsUsers = $users[$separateParentsUsers -> node_user_id];
                    }

                    if($separateParentsUsers) {
                      $separateChildrenLayersUsers[$separateParentsUsers -> node_user_id][$j][$cv -> user_id] = $cv -> user_level;
                    }
                    $thisLayerUsers[$i - 1][$cv -> user_id] = $cv;
                  }
                }
              }
            }

            $countSeparateChildrenLayersUsers = count($separateChildrenLayersUsers);
            if($countSeparateChildrenLayersUsers > 2) {
              $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $parentNodeUser -> user_id . '此用户分离出的结果大于2');
            } else if($countSeparateChildrenLayersUsers == 2) {
              $rightUsersSide = current($separateChildrenLayersUsers);
              $leftUsersSide = next($separateChildrenLayersUsers);
              $userSideUserId = null;

              if($numberOfPlies == 1 && isset($rightUsersSide) && isset($leftUsersSide) && array_key_exists($user -> user_id, $separateChildrenLayersUsers)) {
                $userSideUserId = $user -> node_user_id;
              } else if(
                (isset($rightUsersSide[$numberOfPlies-1]) && !empty($rightUsersSide[$numberOfPlies-1]))
                &&
                (isset($leftUsersSide[$numberOfPlies-1]) && !empty($leftUsersSide[$numberOfPlies-1]))
              ) {
                if(array_key_exists($user -> user_id, $rightUsersSide[$numberOfPlies-1])) {
                  $countLeftUsersSide = count($leftUsersSide[$numberOfPlies-1]);
                  if($countLeftUsersSide > 0 && $countLeftUsersSide < 2) {
                    $rightUsersSideKey = array_keys($separateChildrenLayersUsers);
                    $userSideUserId = $users[$rightUsersSideKey[0]] -> node_user_id;
                    unset($rightUsersSideKey);
                  }
                  unset($countRightUsersSide);
                  unset($countLeftUsersSide);
                } else if(array_key_exists($user -> user_id, $leftUsersSide[$numberOfPlies-1])) {
                  $countRightUsersSide = count($rightUsersSide[$numberOfPlies-1]);
                  if($countRightUsersSide > 0 && $countRightUsersSide < 2) {
                    $leftUsersSideKey = array_keys($separateChildrenLayersUsers);
                    $userSideUserId = $users[$leftUsersSideKey[1]] -> node_user_id;
                    unset($leftUsersSideKey);
                  }
                  unset($countRightUsersSide);
                  unset($countLeftUsersSide);
                } else {
                  $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $user -> user_id . '此用户不存在于分离出的任何节点');
                }
              }
              
              $separateChildrenUsersKeys = array_keys($separateChildrenLayersUsers);
              if(isset($separateChildrenUsersKeys[0]) && isset($separateChildrenUsersKeys[1])) {
                if($users[$separateChildrenUsersKeys[0]] -> node_user_id == $users[$separateChildrenUsersKeys[1]] -> node_user_id) {
                  $this -> getUserTeam($users[$separateChildrenUsersKeys[0]] -> node_user_id) -> team = json_encode($separateChildrenLayersUsers);
                } else {
                  $this -> logger -> warning('LINE: ' . __LINE__ . ',  user_id1: ' .  $users[$separateChildrenUsersKeys[0]] -> user_id . ' 与 user_id2:' . $users[$separateChildrenUsersKeys[1]] -> user_id . ', node_user_id不一致');
                }
                
              } else if(isset($separateChildrenUsersKeys[0])) {
                $this -> getUserTeam($users[$separateChildrenUsersKeys[0]] -> node_user_id) -> team = json_encode($separateChildrenLayersUsers);
              } else if(isset($separateChildrenUsersKeys[1])) {
                $this -> getUserTeam($users[$separateChildrenUsersKeys[1]] -> node_user_id) -> team = json_encode($separateChildrenLayersUsers);
              }

              if(!is_null($userSideUserId) && is_numeric($userSideUserId) && $userSideUserId > 0) {
                $UserWalletGoodsLogModel = new UserWalletGoodsLogModel([
                  'user_id' => $userSideUserId,
                  'from_user_id' => $user -> user_id,
                  'type' => 82,
                  'active' => 1,
                  'is_draw' => 0,
                  'draw_time' => 0,
                  'create_time' => $this -> currentTime,
                  'amount' => $USER_WALLET_GOODS_TOUCH_REWARD['value'],
                  'amount_new' => 0,
                  'amount_old' => 0,
                  'service_charge' => $USER_WALLET_GOODS_TOUCH_REWARD['value'] * $USER_GOODS_REWARD_SERVICE_CHARGE['value'],
                  'remark' => '计划任务 - 层碰奖'
                ]);
                if(!$UserWalletGoodsLogModel -> create()) {
                  $messages = $UserWalletGoodsLogModel -> getMessages();
                  $this -> logger -> error('LINE: ' . __LINE__ . ', $UserWalletGoodsLogModel->create():' .  $messages[0] -> getMessage());
                }
                unset($UserWalletGoodsLogModel);
              }

              unset($userSideUserId);
              unset($rightUsersSide);
              unset($leftUsersSide);
            } else if($countSeparateChildrenLayersUsers < 2) {
              
            } else {
              $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $parentNodeUser -> user_id . '此用户分离出的结果为未知错误');
            }
          } else if($countThisLayerUesrs < 0) {
            
          } else {
            $this -> logger -> warning('LINE: ' . __LINE__ . ', user_id: ' .  $parentNodeUser -> user_id . '此用户出现未知错误count为' . $countThisLayerUesrs);
          }

          unset($separateChildrenLayersUsers);
          unset($thisLayerUsers);
        }
        $numberOfPlies +=1;
        //层碰奖 end

        // 业绩增加
        switch($currentNodeUser -> node_side) {
          case 1:
            $this -> getUserAchievement($parentNodeUser -> user_id) -> increment('day', $USER_EVERY_ONE_ACHIEVEMENT['value'], 0) -> increment('month', $USER_EVERY_ONE_ACHIEVEMENT['value'], 0);

            $this -> db -> begin();
            try {
              if(!$this -> getUserAchievement($parentNodeUser -> user_id) -> update()) {
                throw new \Exception('LINE: ' . __LINE__ . ', getUserAchievement -> update():' .  $messages[0] -> getMessage() . ', user_id:' . $parentNodeUser -> user_id);
              }
              $this -> getUserAchievement($parentNodeUser -> user_id) -> createLog([
                'from_user_id' => $user->user_id,
                'type' => 11,
                'amount' => $USER_EVERY_ONE_ACHIEVEMENT['value'],
                'create_time'=> $this -> currentTime
              ]) -> createLog([
                'from_user_id' => $user->user_id,
                'type' => 12,
                'amount' => $USER_EVERY_ONE_ACHIEVEMENT['value'],
                'create_time'=> $this -> currentTime
              ]);
              $this -> db -> commit();
            } catch(\Exception $e) {
              $this -> db -> rollback();

              $this -> logger -> error($e -> getMessage());
            }

            break;
          case 2:
            $this -> getUserAchievement($parentNodeUser -> user_id) -> increment('day', 0, $USER_EVERY_ONE_ACHIEVEMENT['value']) -> increment('month', 0, $USER_EVERY_ONE_ACHIEVEMENT['value']);
            break;
          default:
            $this -> logger -> warning('LINE: ' . __LINE__ . ',  user_id: ' .  $currentNodeUser -> node_side . '此用户左右区异常');
            break;
        }

        // 见点奖
        if($parentNodeUser -> point_award >= $USER_REGISTER_GET_POINT_REWARD_AMOUNT['value'] && $pointRewardLayer > 0) {
          $UserWalletGoodsLogModel = new UserWalletGoodsLogModel([
            'user_id' => $parentNodeUser->user_id,
            'from_user_id' => $user -> user_id,
            'type' => 84,
            'active' => 1,
            'is_draw' => 0,
            'draw_time' => 0,
            'create_time' => $this -> currentTime,
            'amount' => $USER_REGISTER_GET_POINT_REWARD_AMOUNT['value'],
            'amount_new' => 0,
            'amount_old' => 0,
            'service_charge' => $USER_REGISTER_GET_POINT_REWARD_AMOUNT['value'] * $USER_GOODS_REWARD_SERVICE_CHARGE['value'],
            'remark' => '计划任务 - 见点奖'
          ]);
          if(!$UserWalletGoodsLogModel -> create()) {
            $messages = $UserWalletGoodsLogModel -> getMessages();
            $this -> logger -> warning('LINE: ' . __LINE__ . ', $UserWalletGoodsLogModel->create():' .  $messages[0] -> getMessage());
          }
          unset($UserWalletGoodsLogModel);

          $parentNodeUser -> point_award -= $USER_REGISTER_GET_POINT_REWARD_AMOUNT['value'];
          $this -> getUser($parentNodeUser -> user_id) -> point_award -= $USER_REGISTER_GET_POINT_REWARD_AMOUNT['value'];
        }
        $pointRewardLayer-=1;

        $currentNodeUser = $parentNodeUser;
      }

      unset($currentNodeUser);
      unset($parentNodeUser);
      unset($pointRewardLayer);
      unset($numberOfPlies);

      $user -> is_reward = 1;
      if(!$user -> update()) {
        $messages = $user -> getMessages();
        $this -> logger -> error('LINE: ' . __LINE__ . ', $user -> update():' .  $messages[0] -> getMessage() . ', user_id:' . $user -> user_id);
      }
    }

    if($this -> getUser()) {
      foreach($this -> getUser() as $u) {
        if(!$u -> update()) {
          $messages = $u -> getMessages();
          $this -> logger -> error('LINE: ' . __LINE__ . ', $u -> update():' .  $messages[0] -> getMessage() . ', user_id:' . $u -> user_id);
        }
      }
    }

    if($this -> getUserTeam()) {
      foreach($this -> getUserTeam() as $ut) {
        if(!$ut -> save()) {
          $messages = $ut -> getMessages();
          $this -> logger -> error('LINE: ' . __LINE__ . ', $ut -> update():' .  $messages[0] -> getMessage() . ', user_id:' . $ut -> user_id);
        }
      }
    }

    if($this -> getUserAchievement()) {
      foreach($this -> getUserAchievement() as $ua) {
        if(!$ua -> update()) {
          $messages = $ua -> getMessages();
          $this -> logger -> error('LINE: ' . __LINE__ . ', $ua -> update():' .  $messages[0] -> getMessage() . ', user_id:' . $ua -> user_id);
        }
      }
    }
  }

  private $users;
  public function getUser($user_id = null){
    if(is_null($user_id)) {
      return $this -> users;
    }

    if(isset($this -> users[$user_id])) {
      return $this -> users[$user_id];
    }

    return $this -> users[$user_id] = UserModel::findFirst('user_id = ' . $user_id);
  }

  private $userTeam;
  public function getUserTeam($user_id = null) {
    if(is_null($user_id)) {
      return $this -> userTeam;
    }

    if(isset($this -> userTeam[$user_id])) {
      return $this -> userTeam[$user_id];
    }
    
    $findFirst = UserTeamModel::findFirst('user_id = ' . $user_id);
    if($findFirst) {
      return $this -> userTeam[$user_id] = $findFirst;
    }

    return $this -> userTeam[$user_id] = new UserTeamModel(['user_id' => $user_id]);
  }

  private $userAchievement = [];
  public function getUserAchievement($user_id = null) {
    if(is_null($user_id)) {
      return $this -> userAchievement;
    }

    if(isset($this -> userAchievement[$user_id])) {
      return $this -> userAchievement[$user_id];
    }

    $findFirst = (new \Common\Services\UserAchievementService()) -> findFirst($user_id);
    return $this -> userAchievement[$user_id] = $findFirst['user_achievement'];
  }

  public function testAction() {
    //var_dump('Test');exit;
    $connectionXfh = new \Phalcon\Db\Adapter\Pdo\Mysql([
      'host' => '127.0.0.1',
      'username' => 'root',
      'password' => 'root',
      'dbname' => 'xfh',
      'options' => [
        \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "UTF8"'
      ]
    ]);

    $shopRows = $connectionXfh -> fetchAll('SELECT * FROM request_shop', \Phalcon\Db::FETCH_ASSOC);
    $shopsServiceCodeArray = [];
    foreach($shopRows as $row) {
      $shopsServiceCodeArray[$row['service_code']] = $row;
    }

    $userMdataRows = $connectionXfh -> fetchAll('SELECT * FROM user_mdata', \Phalcon\Db::FETCH_ASSOC);
    $userMdataArray = [];
    foreach($userMdataRows as $row) {
      $userMdataArray[$row['m_cid']] = $row;
    }

    $userRows = $connectionXfh -> fetchAll('SELECT user_id, user_pid, user_referee, user_name, user_status, user_card_name, user_phone, user_level, service_code, user_pwd,user_pwd2,rawdata FROM user ORDER BY user_id DESC', \Phalcon\Db::FETCH_ASSOC);
    $installUserSql = '';
    foreach($userRows as $row) {
      $installUserSql .= 'INSERT INTO user (`user_id`, `service_user_id`, `promotion_user_id`, `node_user_id`, `node_side`, `user_code`, `user_level`, `shop_level`, `status`, `phone`, `real_name`, `password`, `safe_password`, `point_award`, `is_reward`) VALUES ';
      if(isset($shopsServiceCodeArray[$row['service_code']])) {
        $serviceUserId = $shopsServiceCodeArray[$row['service_code']]['user_id'];
      } else {
        $serviceUserId = 0;
      }

      if(isset($userMdataArray[$row['user_id']])) {
        $nodeSide = $userMdataArray[$row['user_id']]['m_lor'];
      } else {
        $nodeSide = 0;
      }

      $shopLevel = $row['user_level'] + 1;

      $installUserSql .= "('{$row['user_id']}', '{$serviceUserId}', '{$row['user_referee']}', '{$row['user_pid']}', '{$nodeSide}', '{$row['user_name']}', '0', '{$shopLevel}', '{$row['user_status']}', '{$row['user_phone']}', '{$row['user_card_name']}', '{$row['user_pwd']}', '{$row['user_pwd2']}', '{$row['rawdata']}', 1);\n";
    }
    file_put_contents(__DIR__ . '/data.sql', $installUserSql);
  }
}